﻿//
// Copyright (c) 2019-2023 BPer
//

#include <bpercapture/mac/BPerVideoCaptureMac.h>
#include <bperutil/BPerAvInfoType.h>

#if BPer_OS_APPLE
void bPer_macv_on_video(uint8_t* data,uint32_t nb,uint64_t ts,void* user){
    BPerVideoCaptureMac* mac;
    if(data==NULL || user==NULL) return;
    mac=(BPerVideoCaptureMac*)user;
    mac->on_video(data,nb,ts);
}

BPerVideoCaptureMac::BPerVideoCaptureMac(BPerVideoInfo *pcontext) {
	m_para = pcontext;

	m_vhandle = new BPerVideoCaptureHandle(pcontext);
	cameraIndex = pcontext->vIndex;
	m_width = m_para->width;
	m_height = m_para->height;

    m_isloop = BPerFalse;
    m_waitState = BPerFalse;


    BPerMacVideoCallback callback;
    callback.user=this;
    callback.on_video=bPer_macv_on_video;

    m_device=(BPerVideoDeviceMac*)bPer_calloc(sizeof(BPerVideoDeviceMac),1);

    bPer_create_macVideo(m_device,(uint32_t)pcontext->width,(uint32_t)pcontext->height,(uint32_t)pcontext->frame,&callback);
    bPer_thread_mutex_init(&m_lock,NULL);
    bPer_thread_cond_init(&m_cond_mess,NULL);

    m_vhandle->setCaptureFormat(BPerNv12);
}

BPerVideoCaptureMac::~BPerVideoCaptureMac() {
    if (m_isStart) {
		stop();
		while (m_isStart) {
			bPer_usleep(1000);
		}
	}

	bPer_delete(m_vhandle);
    bPer_destroy_macVideo(m_device);
    bPer_free(m_device);
    bPer_thread_mutex_destroy(&m_lock);
    bPer_thread_cond_destroy(&m_cond_mess);
}
void BPerVideoCaptureMac::setVideoCaptureStart() {
	m_vhandle->m_isCapture = 1;
}
void BPerVideoCaptureMac::setVideoCaptureStop() {
	m_vhandle->m_isCapture = 0;
}
int32_t BPerVideoCaptureMac::getVideoCaptureState() {
	return m_vhandle->m_isCapture;
}
int32_t BPerVideoCaptureMac::getLivingVideoCaptureState() {
	return m_vhandle->m_isLivingCaptrue;
}
int32_t BPerVideoCaptureMac::getFilmVideoCaptureState() {
	return m_vhandle->m_isFilm;
}

void BPerVideoCaptureMac::setLivingVideoCaptureStart() {
	m_vhandle->m_isLivingCaptrue = 1;
}
void BPerVideoCaptureMac::setLivingVideoCaptureStop() {
	m_vhandle->m_isLivingCaptrue = 0;
}

void BPerVideoCaptureMac::setFilmVideoCaptureStart() {
	m_vhandle->m_isFilm = 1;
}
void BPerVideoCaptureMac::setFilmVideoCaptureStop() {
	m_vhandle->m_isFilm = 0;
}

void BPerVideoCaptureMac::setOutVideoBuffer(BPerVideoBuffer *pbuf) {
	m_vhandle->setVideoBuffer(pbuf);
}
void BPerVideoCaptureMac::setLivingOutVideoBuffer(BPerVideoBuffer *pbuf) {
	m_vhandle->setLivingVideoBuffer(pbuf);
}
void BPerVideoCaptureMac::setFilmOutVideoBuffer(BPerVideoBuffer *pbuf) {
	m_vhandle->setFilmVideoBuffer(pbuf);
}
void BPerVideoCaptureMac::setPreVideoBuffer(BPerVideoBuffer *pbuf) {
	m_vhandle->setPreVideoBuffer(pbuf);
}
void BPerVideoCaptureMac::initstamp() {
	m_vhandle->initstamp();
}


int32_t BPerVideoCaptureMac::init() {

    if(m_device&&m_device->init(m_device->session)!=BPer_Ok){
        bPer_error("mac video capture init fail!");
        return 1;
    }

	return BPer_Ok;
}

void BPerVideoCaptureMac::on_video(uint8_t* data,uint32_t nb,uint64_t ts){
    if (m_vhandle)
        m_vhandle->putBuffer(ts, data,nb);
}


long BPerVideoCaptureMac::m_difftime(struct timeval *p_start,
		struct timeval *p_end) {
	return (p_end->tv_sec - p_start->tv_sec) * 1000000
			+ (p_end->tv_usec - p_start->tv_usec);
}


void BPerVideoCaptureMac::stopLoop() {

    if(m_device&&m_device->stop(m_device->session)!=BPer_Ok){
        bPer_error("mac video capture stop fail!");
        //return;
    }
    m_isloop = BPerFalse;
    if (m_waitState) {
        bPer_thread_mutex_lock(&m_lock);
        bPer_thread_cond_signal(&m_cond_mess);
        bPer_thread_mutex_unlock(&m_lock);

    }
}



void BPerVideoCaptureMac::startLoop() {

    m_isloop=BPerTrue;
    if(m_device&&m_device->start(m_device->session)!=BPer_Ok){
        bPer_error("mac video capture start fail!");
        //return;
    }
    bPer_thread_mutex_lock(&m_lock);
    while (m_isloop) {
        m_waitState = BPerTrue;

        bPer_thread_cond_wait(&m_cond_mess, &m_lock);
        m_waitState = BPerFalse;
    }	            		//end while


    bPer_thread_mutex_unlock(&m_lock);
}
#endif
